package com.atgion.manager.service.impl.client;

import com.atgion.manager.mapper.*;
import com.atgion.manager.service.client.ArticleService;
import com.atgion.spzx.model.bo.blog.*;
import com.atgion.spzx.model.bo.blog.client.QueryCategoryArticlePageListReqVO;
import com.atgion.spzx.model.vo.base.PageResponse;
import com.atgion.spzx.model.vo.base.Result;
import com.atgion.spzx.model.vo.blog.QueryArticleDetailReqVO;
import com.atgion.spzx.model.vo.blog.QueryArticleDetailRspVO;
import com.atgion.spzx.model.vo.blog.client.*;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Lists;
import com.google.common.eventbus.EventBus;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.LocalDateTimeUtil;

import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * @author: 犬小哈
 * @url: www.quanxiaoha.com
 * @date: 2023-04-17 12:08
 * @description: TODO
 **/
@Service
@Slf4j
public class ArticleServiceImpl implements ArticleService {
    @Autowired
    private ArticleMapper articleMapper;

    @Autowired
    private CategoryMapper categoryMapper;

    @Autowired
    private ArticleCategoryRelMapper articleCategoryRelMapper;

    @Autowired
    private TagMapper tagMapper;

    @Autowired
    private ArticleTagRelMapper articleTagRelMapper;
    @Autowired
    private ArticleContentMapper articleContentMapper;

    @Override
    public Result<PageResponse<QueryIndexArticlePageItemRspVO>> queryIndexArticlePageList(QueryIndexArticlePageListReqVO queryIndexArticlePageListReqVO) {
        Long current = queryIndexArticlePageListReqVO.getCurrent();
        Long size = queryIndexArticlePageListReqVO.getSize();


        Page<ArticleDO> page = new Page<>(current, size);
        QueryWrapper<ArticleDO> wrapper = new QueryWrapper<>();
        wrapper.lambda().orderByDesc(ArticleDO::getCreateTime);
        IPage<ArticleDO> articleDOIPage = articleMapper.selectPage(page, wrapper);
        List<ArticleDO> records = articleDOIPage.getRecords();

        List<QueryIndexArticlePageItemRspVO> list = null;
        if (!CollectionUtils.isEmpty(records)) {
            list = records.stream()
                    .map(articleDO -> QueryIndexArticlePageItemRspVO.builder()
                            .id(articleDO.getId())
                            .title(articleDO.getTitle())
                            .titleImage(articleDO.getTitleImage())
                            .description(articleDO.getDescription())
                            .createTime(articleDO.getCreateTime() != null ? 
                                LocalDateTimeUtil.format(articleDO.getCreateTime(), DatePattern.NORM_DATETIME_PATTERN) : null)
                            .build())
                    .collect(Collectors.toList());

            List<Long> articleIds = list.stream().map(p -> p.getId()).collect(Collectors.toList());

            // 设置分类信息

            List<CategoryDO> categoryDOS = categoryMapper.selectList(null);
            Map<Long, String> categoryIdNameMap = categoryDOS.stream().collect(Collectors.toMap(CategoryDO::getId, CategoryDO::getName));


            QueryWrapper<ArticleCategoryRelDO> wrapper1 = new QueryWrapper<>();
            wrapper1.lambda().in(ArticleCategoryRelDO::getArticleId, articleIds);
            List<ArticleCategoryRelDO> articleCategoryRelDOS = articleCategoryRelMapper.selectList(wrapper1);
            list = list.stream().map(p -> {
                Long articleId = p.getId();
                Optional<ArticleCategoryRelDO> optional = articleCategoryRelDOS.stream().filter(rel -> Objects.equals(rel.getArticleId(), articleId)).findFirst();
                if (optional.isPresent()) {
                    ArticleCategoryRelDO articleCategoryRelDO = optional.get();
                    Long categoryId = articleCategoryRelDO.getCategoryId();
                    String categoryName = categoryIdNameMap.get(categoryId);

                    QueryCategoryListItemRspVO queryCategoryListItemRspVO = QueryCategoryListItemRspVO.builder()
                            .id(categoryId)
                            .name(categoryName)
                            .build();
                    p.setCategory(queryCategoryListItemRspVO);
                }
                return p;
            }).collect(Collectors.toList());

            // 设置标签信息

            List<TagDO> tagDOS = tagMapper.selectList(null);
            Map<Long, String> tagIdNameMap = tagDOS.stream().collect(Collectors.toMap(TagDO::getId, TagDO::getName));


            QueryWrapper<ArticleTagRelDO> wrapper2 = new QueryWrapper<>();
            wrapper2.lambda().in(ArticleTagRelDO::getArticleId, articleIds);
            List<ArticleTagRelDO> articleTagRelDOS = articleTagRelMapper.selectList(wrapper2);
            list = list.stream().map(p -> {
                Long articleId = p.getId();
                List<ArticleTagRelDO> articleTagRelDOList = articleTagRelDOS.stream().filter(rel -> Objects.equals(rel.getArticleId(), articleId)).collect(Collectors.toList());

                List<QueryTagListItemRspVO> queryTagListItemRspVOS = Lists.newArrayList();
                articleTagRelDOList.forEach(rel -> {
                    Long tagId = rel.getTagId();
                    String tagName = tagIdNameMap.get(tagId);

                    QueryTagListItemRspVO queryTagListItemRspVO = QueryTagListItemRspVO.builder()
                            .id(tagId)
                            .name(tagName)
                            .build();
                    queryTagListItemRspVOS.add(queryTagListItemRspVO);
                });

                p.setTags(queryTagListItemRspVOS);
                return p;
            }).collect(Collectors.toList());
        }
        PageResponse<QueryIndexArticlePageItemRspVO> success = PageResponse.success(articleDOIPage, list);
        return Result.success(success);
    }

    @Override
    public Result<PageResponse<QueryIndexArticlePageItemRspVO>> queryCategoryArticlePageList(QueryCategoryArticlePageListReqVO queryCategoryArticlePageListReqVO) {
        Long current = queryCategoryArticlePageListReqVO.getCurrent();
        Long size = queryCategoryArticlePageListReqVO.getSize();
        Long queryCategoryId = queryCategoryArticlePageListReqVO.getCategoryId();

        QueryWrapper<ArticleCategoryRelDO> wrapper = new QueryWrapper<>();
        wrapper.lambda().in(ArticleCategoryRelDO::getCategoryId, queryCategoryId);
        List<ArticleCategoryRelDO> articleCategoryRelDOList = articleCategoryRelMapper.selectList(wrapper);

        // 判断该分类下是否存在文章
        if (CollectionUtils.isEmpty(articleCategoryRelDOList)) {
            PageResponse<QueryIndexArticlePageItemRspVO> success = PageResponse.success((IPage) null, (List<QueryIndexArticlePageItemRspVO>) null);
            return Result.success(success);
        }

        List<Long> categoryArticleIds = articleCategoryRelDOList.stream().map(p -> p.getArticleId()).collect(Collectors.toList());

        Page<ArticleDO> page = new Page<>(current, size);
        QueryWrapper<ArticleDO> wrapper2 = new QueryWrapper<>();
        wrapper2.lambda().in(ArticleDO::getId, categoryArticleIds).orderByDesc(ArticleDO::getCreateTime);
        IPage<ArticleDO> articleDOIPage = articleMapper.selectPage(page, wrapper2);
        List<ArticleDO> records = articleDOIPage.getRecords();

        List<QueryIndexArticlePageItemRspVO> list = null;
        if (!CollectionUtils.isEmpty(records)) {
            list = records.stream()
                    .map(articleDO -> QueryIndexArticlePageItemRspVO.builder()
                            .id(articleDO.getId())
                            .title(articleDO.getTitle())
                            .titleImage(articleDO.getTitleImage())
                            .description(articleDO.getDescription())
                            .createTime(articleDO.getCreateTime() != null ? 
                                LocalDateTimeUtil.format(articleDO.getCreateTime(), DatePattern.NORM_DATETIME_PATTERN) : null)
                            .build())
                    .collect(Collectors.toList());

            List<Long> articleIds = list.stream().map(p -> p.getId()).collect(Collectors.toList());

            // 设置分类信息
            List<CategoryDO> categoryDOS = categoryMapper.selectList(null);
            Map<Long, String> categoryIdNameMap = categoryDOS.stream().collect(Collectors.toMap(CategoryDO::getId, CategoryDO::getName));

            QueryWrapper<ArticleCategoryRelDO> wrapper3 = new QueryWrapper<>();
            wrapper3.lambda().in(ArticleCategoryRelDO::getArticleId, articleIds);
            List<ArticleCategoryRelDO> articleCategoryRelDOS = articleCategoryRelMapper.selectList(wrapper3);
            list = list.stream().map(p -> {
                Long articleId = p.getId();
                Optional<ArticleCategoryRelDO> optional = articleCategoryRelDOS.stream().filter(rel -> Objects.equals(rel.getArticleId(), articleId)).findFirst();
                if (optional.isPresent()) {
                    ArticleCategoryRelDO articleCategoryRelDO = optional.get();
                    Long categoryId = articleCategoryRelDO.getCategoryId();
                    String categoryName = categoryIdNameMap.get(categoryId);

                    QueryCategoryListItemRspVO queryCategoryListItemRspVO = QueryCategoryListItemRspVO.builder()
                            .id(categoryId)
                            .name(categoryName)
                            .build();
                    p.setCategory(queryCategoryListItemRspVO);
                }
                return p;
            }).collect(Collectors.toList());

            // 设置标签信息
            List<TagDO> tagDOS = tagMapper.selectList(null);
            Map<Long, String> tagIdNameMap = tagDOS.stream().collect(Collectors.toMap(TagDO::getId, TagDO::getName));

            QueryWrapper<ArticleTagRelDO> wrapper4 = new QueryWrapper<>();
            wrapper4.lambda().in(ArticleTagRelDO::getArticleId, articleIds);
            List<ArticleTagRelDO> articleTagRelDOS = articleTagRelMapper.selectList(wrapper4);
            list = list.stream().map(p -> {
                Long articleId = p.getId();
                List<ArticleTagRelDO> articleTagRelDOList = articleTagRelDOS.stream().filter(rel -> Objects.equals(rel.getArticleId(), articleId)).collect(Collectors.toList());

                List<QueryTagListItemRspVO> queryTagListItemRspVOS = Lists.newArrayList();
                articleTagRelDOList.forEach(rel -> {
                    Long tagId = rel.getTagId();
                    String tagName = tagIdNameMap.get(tagId);

                    QueryTagListItemRspVO queryTagListItemRspVO = QueryTagListItemRspVO.builder()
                            .id(tagId)
                            .name(tagName)
                            .build();
                    queryTagListItemRspVOS.add(queryTagListItemRspVO);
                });

                p.setTags(queryTagListItemRspVOS);
                return p;
            }).collect(Collectors.toList());
        }
        PageResponse<QueryIndexArticlePageItemRspVO> success = PageResponse.success(articleDOIPage, list);
        return Result.success(success);
    }

    @Override
    public Result queryArticleDetail(QueryArticleDetailReqVO queryArticleDetailReqVO) {
        Long articleId = queryArticleDetailReqVO.getArticleId();

        // 判断文章是否存在
        ArticleDO articleDO =articleMapper.selectById(articleId);

        if (Objects.isNull(articleDO)) {
//            throw new ResourceNotFoundException();
        }

        QueryWrapper<ArticleContentDO> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(ArticleContentDO::getArticleId, articleId);
        ArticleContentDO articleContentDO = articleContentMapper.selectOne(wrapper);

        QueryArticleDetailRspVO vo = QueryArticleDetailRspVO.builder()
                .title(articleDO.getTitle())
                .updateTime(articleDO.getUpdateTime())
                .content(articleContentDO.getContent()) //修改点
                .readNum(articleDO.getReadNum())
                .build();

        // 查询文章所属分类
        QueryWrapper<ArticleCategoryRelDO> wrapper2 = new QueryWrapper<>();
        wrapper2.lambda().eq(ArticleCategoryRelDO::getArticleId, articleId);
        ArticleCategoryRelDO articleCategoryRelDO = articleCategoryRelMapper.selectOne(wrapper2);

        QueryWrapper<CategoryDO> wrapper3 = new QueryWrapper<>();
        wrapper3.lambda().eq(CategoryDO::getId, articleCategoryRelDO.getCategoryId());
        CategoryDO categoryDO =categoryMapper.selectOne(wrapper3);
        vo.setCategoryId(categoryDO.getId());
        vo.setCategoryName(categoryDO.getName());

        // 查询文章标签
        QueryWrapper<ArticleTagRelDO> wrapper4 = new QueryWrapper<>();
        wrapper4.lambda().eq(ArticleTagRelDO::getArticleId, articleId);
        List<ArticleTagRelDO> articleTagRelDOS = articleTagRelMapper.selectList(wrapper4);
        List<Long> tagIds = articleTagRelDOS.stream().map(p -> p.getTagId()).collect(Collectors.toList());

        QueryWrapper<TagDO> wrapper5 = new QueryWrapper<>();
        wrapper5.lambda().in(TagDO::getId, tagIds);
        List<TagDO> tagDOS =tagMapper.selectList(wrapper5);

        List<QueryTagListItemRspVO> queryTagListItemRspVOS = tagDOS.stream()
                .map(p -> QueryTagListItemRspVO.builder().id(p.getId()).name(p.getName()).build()).collect(Collectors.toList());
        vo.setTags(queryTagListItemRspVOS);

        // 上一篇
        QueryWrapper<ArticleDO> wrapper6 = new QueryWrapper<>();
        wrapper6.lambda().orderByAsc(ArticleDO::getId).gt(ArticleDO::getId, articleId).last("limit 1");
        ArticleDO preArticle = articleMapper.selectOne(wrapper6);
        if (Objects.nonNull(preArticle)) {
            QueryArticleLinkRspVO prevArticleVO = QueryArticleLinkRspVO.builder()
                    .title(preArticle.getTitle())
                    .id(preArticle.getId())
                    .build();
            vo.setPreArticle(prevArticleVO);
        }

        // 下一篇
        QueryWrapper<ArticleDO> wrapper7 = new QueryWrapper<>();
        wrapper7.lambda().orderByDesc(ArticleDO::getId).lt(ArticleDO::getId, articleId).last("limit 1");
        ArticleDO nextArticle = articleMapper.selectOne(wrapper7);
        if (Objects.nonNull(nextArticle)) {
            QueryArticleLinkRspVO nextArticleVO = QueryArticleLinkRspVO.builder()
                    .title(nextArticle.getTitle())
                    .id(nextArticle.getId())
                    .build();
            vo.setNextArticle(nextArticleVO);
        }

        // 发送消息事件
        log.info("发送 PV +1 消息事件");
//        eventBus.post(ArticleEvent.builder().articleId(articleId).message(EventEnum.PV_INCREASE.getMessage()).build());

        return Result.success(vo);
    }

    @Override
    public Result<PageResponse<QueryIndexArticlePageItemRspVO>> queryTagArticlePageList(QueryTagArticlePageListReqVO queryTagArticlePageListReqVO) {
        Long current = queryTagArticlePageListReqVO.getCurrent();
        Long size = queryTagArticlePageListReqVO.getSize();
        Long queryTagId = queryTagArticlePageListReqVO.getTagId();

        QueryWrapper<ArticleTagRelDO> wrapper = new QueryWrapper<>();
        wrapper.lambda().in(ArticleTagRelDO::getTagId, queryTagId);
        List<ArticleTagRelDO> articleTagRelDOS1 = articleTagRelMapper.selectList(wrapper);

        // 判断该分类下是否存在文章
        if (CollectionUtils.isEmpty(articleTagRelDOS1)) {
            PageResponse<QueryIndexArticlePageItemRspVO> success = PageResponse.success((IPage) null, (List<QueryIndexArticlePageItemRspVO>) null);
            return Result.success(success);
        }

        List<Long> tagArticleIds = articleTagRelDOS1.stream().map(p -> p.getArticleId()).collect(Collectors.toList());


        Page<ArticleDO> page = new Page<>(current, size);
        QueryWrapper<ArticleDO> wrapper1 = new QueryWrapper<>();
        wrapper1.lambda().in(ArticleDO::getId, tagArticleIds).orderByDesc(ArticleDO::getCreateTime);
        IPage<ArticleDO> articleDOIPage = articleMapper.selectPage(page, wrapper1);
        List<ArticleDO> records = articleDOIPage.getRecords();

        List<QueryIndexArticlePageItemRspVO> list = null;
        if (!CollectionUtils.isEmpty(records)) {
            list = records.stream()
                    .map(articleDO -> QueryIndexArticlePageItemRspVO.builder()
                            .id(articleDO.getId())
                            .title(articleDO.getTitle())
                            .titleImage(articleDO.getTitleImage())
                            .description(articleDO.getDescription())
                            .createTime(articleDO.getCreateTime() != null ? 
                                LocalDateTimeUtil.format(articleDO.getCreateTime(), DatePattern.NORM_DATETIME_PATTERN) : null)
                            .build())
                    .collect(Collectors.toList());

            List<Long> articleIds = list.stream().map(p -> p.getId()).collect(Collectors.toList());

            // 设置分类信息
            List<CategoryDO> categoryDOS =categoryMapper.selectList(null);
            Map<Long, String> categoryIdNameMap = categoryDOS.stream().collect(Collectors.toMap(CategoryDO::getId, CategoryDO::getName));

            QueryWrapper<ArticleCategoryRelDO> wrapper2 = new QueryWrapper<>();
            wrapper2.lambda().in(ArticleCategoryRelDO::getArticleId, articleIds);
            List<ArticleCategoryRelDO> articleCategoryRelDOS = articleCategoryRelMapper.selectList(wrapper2);
            list = list.stream().map(p -> {
                Long articleId = p.getId();
                Optional<ArticleCategoryRelDO> optional = articleCategoryRelDOS.stream().filter(rel -> Objects.equals(rel.getArticleId(), articleId)).findFirst();
                if (optional.isPresent()) {
                    ArticleCategoryRelDO articleCategoryRelDO = optional.get();
                    Long categoryId = articleCategoryRelDO.getCategoryId();
                    String categoryName = categoryIdNameMap.get(categoryId);

                    QueryCategoryListItemRspVO queryCategoryListItemRspVO = QueryCategoryListItemRspVO.builder()
                            .id(categoryId)
                            .name(categoryName)
                            .build();
                    p.setCategory(queryCategoryListItemRspVO);
                }
                return p;
            }).collect(Collectors.toList());

            // 设置标签信息
            List<TagDO> tagDOS = tagMapper.selectList(null);
            Map<Long, String> tagIdNameMap = tagDOS.stream().collect(Collectors.toMap(TagDO::getId, TagDO::getName));

            QueryWrapper<ArticleTagRelDO> wrapper3 = new QueryWrapper<>();
            wrapper3.lambda().in(ArticleTagRelDO::getArticleId, articleIds);
            List<ArticleTagRelDO> articleTagRelDOS = articleTagRelMapper.selectList(wrapper3);
            list = list.stream().map(p -> {
                Long articleId = p.getId();
                List<ArticleTagRelDO> articleTagRelDOList = articleTagRelDOS.stream().filter(rel -> Objects.equals(rel.getArticleId(), articleId)).collect(Collectors.toList());

                List<QueryTagListItemRspVO> queryTagListItemRspVOS = Lists.newArrayList();
                articleTagRelDOList.forEach(rel -> {
                    Long tagId = rel.getTagId();
                    String tagName = tagIdNameMap.get(tagId);

                    QueryTagListItemRspVO queryTagListItemRspVO = QueryTagListItemRspVO.builder()
                            .id(tagId)
                            .name(tagName)
                            .build();
                    queryTagListItemRspVOS.add(queryTagListItemRspVO);
                });

                p.setTags(queryTagListItemRspVOS);
                return p;
            }).collect(Collectors.toList());
        }
        PageResponse<QueryIndexArticlePageItemRspVO> success = PageResponse.success(articleDOIPage, list);
        return Result.success(success);
    }
}
